﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RFIDStockManagement.Model.Public;
using RFIDStockManagement.Common.Public.Enums;

namespace IOReadWriter
{
    sealed class RfidCacheManager
    {
        private static Dictionary<string, DateTime> m_dctInStockRfidList = new Dictionary<string, DateTime>();
        private static List<string> m_lstInStockRfidDataInfoList = new List<string>();
        private static Dictionary<string, DateTime> m_dctOutStockRfidList = new Dictionary<string, DateTime>();
        private static List<string> m_lstOutStockRfidDataInfoList = new List<string>();
        private static Dictionary<string, DateTime> m_dctOutCheckRfidList = new Dictionary<string, DateTime>();
        private static List<string> m_lstOutCheckRfidDataInfoList = new List<string>();
        //盘点
        private static Dictionary<string, object> m_dctStockCheckRfidList = new Dictionary<string, object>();
        private static List<string> m_lstStockCheckRfidDataInfoList = new List<string>();

        public static int ReadPerCount = 100;
        public static int ClearPerCount = 10000;

        public static string[] ReadRfidDataInfo(int iStart, out int iNewStart, EnumIOStockOperate enmOperate)
        {
            string[] lstResult = null;
            iNewStart = iStart;
            switch (enmOperate)
            {
                case EnumIOStockOperate.InStock:
                    if (m_lstInStockRfidDataInfoList.Count > iStart)
                    {
                        int iCount = Math.Min(ReadPerCount, m_lstInStockRfidDataInfoList.Count - iStart);
                        lstResult = new string[iCount];
                        m_lstInStockRfidDataInfoList.CopyTo(iStart, lstResult, 0, iCount);
                        int iIndex = iStart + iCount - 1;
                        iNewStart = Clear(iIndex, enmOperate);
                    }
                    break;
                case EnumIOStockOperate.OutStock:
                    if (m_lstOutStockRfidDataInfoList.Count > iStart)
                    {
                        int iCount = Math.Min(ReadPerCount, m_lstOutStockRfidDataInfoList.Count - iStart);
                        lstResult = new string[iCount];
                        m_lstOutStockRfidDataInfoList.CopyTo(iStart, lstResult, 0, iCount);
                        int iIndex = iStart + iCount - 1;
                        iNewStart = Clear(iIndex, enmOperate);
                    }
                    break;
                case EnumIOStockOperate.OutCheck:
                    if (m_lstOutCheckRfidDataInfoList.Count > iStart)
                    {
                        int iCount = Math.Min(ReadPerCount, m_lstOutCheckRfidDataInfoList.Count - iStart);
                        lstResult = new string[iCount];
                        m_lstOutCheckRfidDataInfoList.CopyTo(iStart, lstResult, 0, iCount);
                        int iIndex = iStart + iCount - 1;
                        iNewStart = Clear(iIndex, enmOperate);
                    }
                    break;
                case EnumIOStockOperate.StockCheck:
                    if (m_lstStockCheckRfidDataInfoList.Count > iStart)
                    {
                        int iCount = Math.Min(ReadPerCount, m_lstStockCheckRfidDataInfoList.Count - iStart);
                        lstResult = new string[iCount];
                        m_lstStockCheckRfidDataInfoList.CopyTo(iStart, lstResult, 0, iCount);
                        int iIndex = iStart + iCount - 1;
                        iNewStart = Clear(iIndex, enmOperate);
                    }
                    break;
            }
            ClearEpcCache();

            return lstResult;
        }

        private static int Clear(int iStart, EnumIOStockOperate enmOperate)
        {
            int iResult = iStart + 1;
            if (iStart >= ClearPerCount)
            {
                switch (enmOperate)
                {
                    case EnumIOStockOperate.InStock:
                        lock (m_lstInStockRfidDataInfoList)
                        {
                            m_lstInStockRfidDataInfoList.RemoveRange(0, iStart + 1);
                            iResult = 0;
                        }
                        break;
                    case EnumIOStockOperate.OutStock:
                        lock (m_lstOutStockRfidDataInfoList)
                        {
                            m_lstOutStockRfidDataInfoList.RemoveRange(0, iStart + 1);
                            iResult = 0;
                        }
                        break;
                    case EnumIOStockOperate.OutCheck:
                        lock (m_lstOutCheckRfidDataInfoList)
                        {
                            m_lstOutCheckRfidDataInfoList.RemoveRange(0, iStart + 1);
                            iResult = 0;
                        }
                        break;
                    case EnumIOStockOperate.StockCheck:
                        lock (m_lstStockCheckRfidDataInfoList)
                        {
                            m_lstStockCheckRfidDataInfoList.RemoveRange(0, iStart + 1);
                            iResult = 0;
                        }
                        break;
                }
            }

            return iResult;
        }

        private static DateTime m_UpdateEpcTime = DateTime.Now;
        private static double m_EpcCacheSecond = 20;
        private static void ClearEpcCache()
        {
            DateTime dtNow = DateTime.Now;
            if ((dtNow - m_UpdateEpcTime).TotalSeconds >= m_EpcCacheSecond)
            {
                //lock (m_dctInStockRfidList)
                //{
                //    ClearItemEpcCache(dtNow, m_dctInStockRfidList);
                //}

                //lock (m_dctOutStockRfidList)
                //{
                //    ClearItemEpcCache(dtNow, m_dctOutStockRfidList);
                //}

                lock (m_dctOutCheckRfidList)
                {
                    ClearItemEpcCache(dtNow, m_dctOutCheckRfidList);
                }
                m_UpdateEpcTime = dtNow;
            }
        }
        private static void ClearItemEpcCache(DateTime dtNow, Dictionary<string, DateTime> dctEpc)
        {
            List<string> lstEpc = new List<string>();
            foreach (var item in dctEpc)
            {
                if ((dtNow - item.Value).TotalSeconds >= m_EpcCacheSecond)
                {
                    lstEpc.Add(item.Key);
                }
            }
            foreach (string epc in lstEpc)
            {
                dctEpc.Remove(epc);
            }
        }

        public static void WriteRfidDataInfo(string rfid, EnumIOStockOperate enmOperate)
        {
            switch (enmOperate)
            {
                case EnumIOStockOperate.InStock:
                    lock (m_lstInStockRfidDataInfoList)
                    {
                        lock (m_dctInStockRfidList)
                        {
                            if (m_dctInStockRfidList.ContainsKey(rfid) == false)
                            {
                                m_lstInStockRfidDataInfoList.Add(rfid);
                                m_dctInStockRfidList.Add(rfid, DateTime.Now);
                            }
                        }
                    }
                    break;
                case EnumIOStockOperate.OutStock:
                    lock (m_lstOutStockRfidDataInfoList)
                    {
                        lock (m_dctOutStockRfidList)
                        {
                            if (m_dctOutStockRfidList.ContainsKey(rfid) == false)
                            {
                                m_lstOutStockRfidDataInfoList.Add(rfid);
                                m_dctOutStockRfidList.Add(rfid, DateTime.Now);
                            }
                        }
                    }
                    break;
                case EnumIOStockOperate.OutCheck:
                    lock (m_lstOutCheckRfidDataInfoList)
                    {
                        lock (m_dctOutCheckRfidList)
                        {
                            if (m_dctOutCheckRfidList.ContainsKey(rfid) == false)
                            {
                                m_lstOutCheckRfidDataInfoList.Add(rfid);
                                m_dctOutCheckRfidList.Add(rfid, DateTime.Now);
                            }
                        }
                    }
                    break;
                case EnumIOStockOperate.StockCheck:
                    lock (m_lstStockCheckRfidDataInfoList)
                    {
                        if (m_dctStockCheckRfidList.ContainsKey(rfid) == false)
                        {
                            m_lstStockCheckRfidDataInfoList.Add(rfid);
                            m_dctStockCheckRfidList.Add(rfid, null);
                        }
                    }
                    break;
            }
        }

        public static void ClearAllCache(EnumIOStockOperate enmOperate)
        {
            switch (enmOperate)
            {
                case EnumIOStockOperate.InStock:
                    m_dctInStockRfidList.Clear();
                    m_lstInStockRfidDataInfoList.Clear();
                    break;
                case EnumIOStockOperate.OutStock:
                    m_dctOutStockRfidList.Clear();
                    m_lstOutStockRfidDataInfoList.Clear();
                    break;
                case EnumIOStockOperate.OutCheck:
                    m_dctOutCheckRfidList.Clear();
                    m_lstOutCheckRfidDataInfoList.Clear();
                    break;
                case EnumIOStockOperate.StockCheck:
                    m_dctStockCheckRfidList.Clear();
                    m_lstStockCheckRfidDataInfoList.Clear();
                    break;
            }
        }
    }
}
